
Ext.ns('X');

//==========================================//
//                  TOOLS                   //
//==========================================//

// obtener el objeto apartir de su id
// funciona tanto pata componentes como para stores
X.get = function(id)  { 
    var r = Ext.getCmp(id); 
    if (r) return r;
    else   return Ext.StoreMgr.get(id);
}

// return el valor del componente
X.value = function(id) {
    if (X.get(id).getXType() == 'datefield'){
        if (X.get(id).getValue() == '')
            return '';
        else
            return X.get(id).getValue().format('d/m/Y');
    }
    else return X.get(id).getValue();
}

// retorna true si el componente.value es vacio
X.isempty = function(id) {
    return Ext.isEmpty(X.value(id));
}

// cambia las propiedades del componente
X.set     = function(id,v){ X.get(id).setValue(v); }
X.load    = function(id,v){ X.get(id).loadData(v); }
X.focus   = function(id)  { X.get(id).focus   ();  }
X.disable = function(id)  { X.get(id).disable ();  }
X.enable  = function(id)  { X.get(id).enable  ();  }
X.show    = function(id)  { X.get(id).show    ();  }
X.hide    = function(id)  { X.get(id).hide    ();  }

// redirecciona al url
X.redir = function(url) { window.location=url; }

// realiza bind de las variables a los parametros de una funcion
X.call = function(f,p){
    return function(){
        f(this.p);
    }.bind({p:p});
}

// recargar el grid o combo
X.reload = function(id){
    if (X.get(id).getXType() == 'grid' && typeof this.bbar != 'undefined'){
        X.get(id).getBottomToolbar().doRefresh();
    }
}

//==========================================//
//                 MESSAGE                  //
//==========================================//


Ext.ns('X.msg');

// si se especifica el handler, al cerrar el mensaje se ejecuta la funcion handler
X.msg.success = function(text, handler){
    if (typeof handler == 'undefined')
        Ext.Msg.show({title:'Mensaje', msg: text, icon: Ext.Msg.INFO,  buttons: Ext.Msg.OK});
    else
        Ext.Msg.show({title:'Mensaje', msg: text, icon: Ext.Msg.INFO,  buttons: Ext.Msg.OK, fn:handler});
}
// si se especifica el handler, al cerrar el mensaje se ejecuta la funcion handler
X.msg.failure = function(text, handler){
    if (typeof handler == 'undefined')
        Ext.Msg.show({title:'Mensaje', msg: text, icon: Ext.Msg.ERROR, buttons: Ext.Msg.OK});
    else
        Ext.Msg.show({title:'Mensaje', msg: text, icon: Ext.Msg.ERROR, buttons: Ext.Msg.OK, fn:handler});
}
// se ejecuta la funcion handler si se elige 'yes'
// siempre debe especificar el handler
X.msg.confirm = function(text, handler){
    Ext.Msg.show({title:'Mensaje', msg: text, icon: Ext.Msg.INFO, buttons: {yes:'Sí', no: 'No'}, fn:function(btn){
        if (btn == 'yes'){
            handler();
        }
    }});
}

//==========================================//
//                  EVENT                   //
//==========================================//

Ext.ns('X.event');

// llamar a func si componente con id recibe el evento
X.event.keypress = function(id, func){
    X.get(id).addListener('keypress', func);
}
X.event.check = function(id, func){
    X.get(id).addListener('check', func);
}
X.event.button = function(id, func){
    X.get(id).setHandler(func);
}
// si se aprieta el enter, salta al campo 'to'
X.event.jump = function(from, to){
    X.event.keypress(from, function(field, event){
        if (event.getKey()==13){
            if (typeof X.get(from).initialConfig.listeners      != 'undefined')
            if (typeof X.get(from).initialConfig.listeners.blur != 'undefined')
                X.get(from).initialConfig.listeners.blur(X.get(from));
            X.focus(to);
        }
    });
}
// si se aprieta el enter, aprieta el boton 'to'
X.event.press = function(from, to){
    X.event.keypress(from, function(field, event){
        if (event.getKey()==13){
            if (typeof X.get(from).initialConfig.listeners      != 'undefined')
            if (typeof X.get(from).initialConfig.listeners.blur != 'undefined')
                X.get(from).initialConfig.listeners.blur(X.get(from));
            X.focus(to);
            X.get(to).handler.call();
        }
    });
}

//==========================================//
//                  FORM                    //
//==========================================//

Ext.ns('X');

X.ajax = function(c){
    
    // mostrar la barra de espera mientras esta esperando la respuesta ajax
    //   "targetId" es una propiedad definida por el usuario para cargar el 
    //   mask a un componente especifico
    if (typeof c.targetId == 'undefined')
        c.mask = new Ext.LoadMask(Ext.getBody(), {msg:"Procesando..."});
    else
        c.mask = new Ext.LoadMask(X.get(c.targetId).body, {msg:"Procesando..."});
    c.mask.show();
    
    // entra en success si no hubo problemas con el ajax
    //   si el servidor respondio con Msg::Success(), llama a afterSuccess si esta definido
    //   si el servidor respondio con Msg::Failure(), llama a afterFailure si esta definido
    c.success = function(response, opts){
        // termina la barra de espera
        c.mask.hide();
        try{
            this.obj = Ext.decode(response.responseText);
            if (this.obj.success){
                if (typeof c.afterSuccess == 'undefined') {
                    // si har mensaje, pero sin handler
                    if (Ext.isEmpty(this.obj.msg)==false)
                        X.msg.success(this.obj.msg);
                    // si no hay ni mensaje ni handler, no hacer nada
                }else{
                    // si hay el handler y el mensaje
                    if (Ext.isEmpty(this.obj.msg)==false)
                        X.msg.success(this.obj.msg, X.call(c.afterSuccess,this.obj));
                    // si hay el handler, pero no el mensaje
                    else c.afterSuccess(this.obj);
                }
            }
            else{
                // el failure, se supone que viene con un mensaje
                // *) cualquier cosa, se puede imitar el codigo del success
                if (typeof c.afterFailure == 'undefined') {
                    if (Ext.isEmpty(this.obj.msg)==false)
                        X.msg.failure(this.obj.msg);
                }else{
                    if (Ext.isEmpty(this.obj.msg)==false)
                            X.msg.failure(this.obj.msg, X.call(c.afterFailure,this.obj));
                    else
                        c.afterFailure(this.obj);
                }
            }
        }
        // error, probablemente al decodificar el json
        catch(e){
            X.msg.failure('Ajax error.');
        }
    }
    // algun problema en la transmision
    c.failure = function(response, opts){
        c.mask.hide();
        X.msg.failure('Ajax error.');
    }
    
    Ext.Ajax.request(c);
};

//==========================================//
//                  FORM                    //
//==========================================//

Ext.ns('X.form');

X.form.panel = function(c){
    c.layout   = 'absolute';
    c.renderTo = 'layout_content';
    c.frame    = true;
    c.resizable = false;
    return new Ext.form.FormPanel(c);
}

//Agregado
X.form.fieldset = function(c){return new Ext.form.FieldSet(c);}
X.form.radio    = function(c){return new Ext.form.Radio(c);}
X.form.check    = function(c){return new Ext.form.Checkbox(c);}
X.form.time     = function(c){return new Ext.form.TimeField(c);}


X.form.button   = function(c){return new Ext.Button     (c);}
X.form.label    = function(c){return new Ext.form.Label (c);}
X.form.hidden   = function(c){return new Ext.form.Hidden(c);}
X.form.text     = function(c){
    c.enableKeyEvents = true;
    c.selectOnFocus   = true;
    // maxlen: cantidad de caracteres permitidos. propiedad definido por el usuario.
    // si esta definido, crea la restriccion en forma de Ext
    if (typeof c.maxlen != 'undefined')
        c.autoCreate = {tag:'input', maxlength:c.maxlen};
    return new Ext.form.TextField(c);
}
X.form.number = function(c){
    c.enableKeyEvents = true;
    c.selectOnFocus   = true;
    // maxlen: cantidad de caracteres permitidos. propiedad definida por el usuario.
    // si esta definido, crea la restriccion en forma de Ext
    if (typeof c.maxlen != 'undefined')
        c.autoCreate = {tag:'input', maxlength:c.maxlen};
    return new Ext.form.NumberField(c);
}
X.form.email     = function(c){
    c.enableKeyEvents = true;
    c.selectOnFocus   = true;
    c.vtype = 'email';
    vtypeText  : 'email inválido';
    // maxlen: cantidad de caracteres permitidos. propiedad definido por el usuario.
    // si esta definido, crea la restriccion en forma de Ext
    if (typeof c.maxlen != 'undefined')
        c.autoCreate = {tag:'input', maxlength:c.maxlen};
    return new Ext.form.TextField(c);
}

X.form.pass = function(c){
    c.enableKeyEvents = true;
    c.selectOnFocus   = true;
    c.inputType       = 'password';
    // maxlen: cantidad de caracteres permitidos. propiedad definido por el usuario.
    // si esta definido, crea la restriccion en forma de Ext
    if (typeof c.maxlen != 'undefined')
        c.autoCreate = {tag:'input', maxlength:c.maxlen};
    return new Ext.form.TextField(c);
}
X.form.combo = function(c){
    c.enableKeyEvents = true;
    c.selectOnFocus   = true;
    c.forceSelection  = true;
    c.mode            = 'local';
    c.triggerAction   = 'all';
    // propiedad definida por el usuario: dfield, vfield, storeId
    c.displayField    = c.dfield;
    c.hiddenName      = c.vfield;
    c.valueField      = c.vfield;
    c.store           = X.get(c.storeId);
    // [forceSelection=true] no funciona al hacer X.event.jump
    //   entonces, en X.event.jump se llama forzadamente al evento blur
    //   Ejemplo: seleccione un elemento, escriba garabato en el combo, apriete enter.
    c.listeners       = {
        'blur':function(combo){
            // si no se limpia el filter, el setValue puede no encontrar los valores deseados
            combo.getStore().clearFilter();
            combo.setValue(combo.getValue());
        }
    }
    return new Ext.form.ComboBox(c);
}
X.form.date = function(c){
    c.enableKeyEvents = true;
    c.selectOnFocus   = true
    c.validateOnBlur  = false;
    c.format      = 'd/m/Y';
    c.altFormats  = 'd/m/Y|Y-m-d H:i:s|c';
    c.invalidText = 'fecha inválida';
    // consistencia de los datos
    //   "lastValidValue" es una propiedad definida por el usuario
    c.listeners       = {
        // si se ingresa una fecha valida, guarga
        'keypress':function(field){
            if (field.isValid())
                field.lastValidValue = field.getValue();
        },
        // si se termina la edicion con dato invalido, 
        // utiliza la fecha valida guardada
        'blur':function(field){
            if (field.isValid()==false)
                field.setValue(field.lastValidValue);
        }
    }
    return new Ext.form.DateField(c);
}

//==========================================//
//                  GRID                    //
//==========================================//

Ext.ns('X.grid');

X.grid.editor = function(c){
    c.stripeRows   = true;
    c.loadMask     = true;
    c.monitorValid = true;
    c.sm           = new Ext.grid.RowSelectionModel();
    c.store = X.get(c.storeId);

/*var g = new Ext.grid.EditorGridPanel(c);

alert(g.getSelectionModel());

    return g;*/
    //return new Ext.extend(c,Ext.grid.EditorGridPanel);
    return new Ext.grid.EditorGridPanel(c);
}

X.grid.panel = function(c){
    c.stripeRows = true;
    c.loadMask   = true;
    c.store = X.get(c.storeId);
    // Arregla el siguiente problema:
    //   No se actualiza correctamente la posicion de la pagina actual
    //   si el reload trae menos cantidad de paginas que la posicion actual
    //   Ej: Esta en la pagina 12/20. El reload trae ahora solamente 8 paginas.
    //       Deberia mostrar 8/8, pero muestra 20/8
    c.store.addListener('load', function(){
        if (typeof this.bbar != 'undefined'){
            var now  = this.bbar.cursor/this.bbar.pageSize+1;
            var max  = Math.ceil(((this.store.getTotalCount()-0.5)/this.bbar.pageSize));
            if (now > max && max > 0){
                this.bbar.changePage(max);
            }
        }
    }.bind(c));
    
    return new Ext.grid.GridPanel(c);
}
X.grid.paging = function(c){
    c.buttonAlign = 'center';
    c.store = X.get(c.storeId);
    return new Ext.PagingToolbar(c);
}
X.grid.text = function(c){ 
    c.menuDisabled = true;
    c.sortable     = true;
    return new Ext.grid.Column(c);
}
/* no es posible editar */
X.grid.label = function(c){
    c.menuDisabled = true;
    c.sortable     = true;
    c.editable      = false;
    return new Ext.grid.Column(c);
}
X.grid.number = function(c){
    c.menuDisabled = true;
    c.sortable     = true;
    return new Ext.grid.NumberColumn(c);
}
X.grid.money = function(c){
    c.menuDisabled = true;
    c.sortable     = true;
    c.align        = 'right';
    c.format       = '0.000 Gs/i';
    return new Ext.grid.NumberColumn(c);
}
X.grid.date = function(c){
    c.menuDisabled = true;
    c.sortable     = true;
    c.align        = 'right';
    c.renderer     = function(val){
        if (!val)                 return '';
        if ( val instanceof Date) return val.format('d/m/Y');
        try{ return Date.parseDate(val, 'Y-m-d'      ).format('d/m/Y'); }catch(e){
        try{ return Date.parseDate(val, 'Y-m-d H:i:s').format('d/m/Y'); }catch(e){
            X.msg.failure(e.message);
        }}
    }
    return new Ext.grid.Column(c);
}
X.grid.edit = function(c){
    c.width        = 28;
    c.menuDisabled = true;
    c.icon         = '/img/icon_editar.png';
    c.tooltip      = 'Editar';
    //custom handler function(row)
        // guardar el custom handler
        c.myHandler = c.handler;
        // generar el handler valido, y conecta con el custom
        c.handler = function(g, r){
            c.myHandler(g.getStore().getAt(r));
        }.bind(c);
        
    var col = new Ext.grid.ActionColumn(c);

    // "hideIf" es una propiedad definida por el usuario
    //   que oculta el boton del actionColumn si retorna true
        col.originalRenderer = col.renderer;
        col.renderer = function(v,m,r,ri,ci,s){
            if (typeof col.hideIf != 'undefined' && col.hideIf(v,m,r,ri,ci,s))
                return '';
            else
                return col.originalRenderer(v,m);
        }.bind(col);
    return col;
}
X.grid.remove = function(c){
    c.width        = 28;
    c.menuDisabled = true;
    c.icon         = '/img/icon_eliminar.png';
    c.tooltip      = 'Eliminar';
    //custom handler function(row)
        // guardar el custom handler
        c.myHandler = c.handler;
        // generar el handler valido, y conecta con el custom
        c.handler = function(g, r){
            c.myHandler(g.getStore().getAt(r));
        }.bind(c);
    
    
    var col = new Ext.grid.ActionColumn(c);

    // "hideIf" es una propiedad definida por el usuario
    //   que oculta el boton del actionColumn si retorna true
        col.originalRenderer = col.renderer;
        col.renderer = function(v,m,r,ri,ci,s){
            if (typeof col.hideIf != 'undefined' && col.hideIf(v,m,r,ri,ci,s))
                return '';
            else
                return col.originalRenderer(v,m);
        }.bind(col);
    return col
}
X.grid.Import = function(c){
    c.width        = 28;
    c.menuDisabled = true;
    c.icon         = '/img/icon_importar.png';
    c.tooltip      = 'Importar';
    //custom handler function(row)
        // guardar el custom handler
        c.myHandler = c.handler;
        // generar el handler valido, y conecta con el custom
        c.handler = function(g, r){
            c.myHandler(g.getStore().getAt(r));
        }.bind(c);
    
    
    var col = new Ext.grid.ActionColumn(c);

    // "hideIf" es una propiedad definida por el usuario
    //   que oculta el boton del actionColumn si retorna true
        col.originalRenderer = col.renderer;
        col.renderer = function(v,m,r,ri,ci,s){
            if (typeof col.hideIf != 'undefined' && col.hideIf(v,m,r,ri,ci,s))
                return '';
            else
                return col.originalRenderer(v,m);
        }.bind(col);
    return col
}
X.grid.ok = function(c){
    c.width        = 28;
    c.menuDisabled = true;
    c.icon         = '/img/icon_ok.png';
    c.tooltip      = 'Validar';
    //custom handler function(row)
    // guardar el custom handler
    c.myHandler = c.handler;
    // generar el handler valido, y conecta con el custom
    c.handler = function(g, r){
        c.myHandler(g.getStore().getAt(r));
    }.bind(c);

    var col = new Ext.grid.ActionColumn(c);

    // "hideIf" es una propiedad definida por el usuario
    //   que oculta el boton del actionColumn si retorna true
    col.originalRenderer = col.renderer;
    col.renderer = function(v,m,r,ri,ci,s){
        if (typeof col.hideIf != 'undefined' && col.hideIf(v,m,r,ri,ci,s))
            return '';
        else
            return col.originalRenderer(v,m);
    }.bind(col);
    return col;
}

X.grid.show = function(c){
    c.width        = 50;
    c.menuDisabled = true;
    c.icon         = '/img/icon_ver.png';
    c.tooltip      = 'Ver Detalles';
    //custom handler function(row)
    // guardar el custom handler
    c.myHandler = c.handler;
    // generar el handler valido, y conecta con el custom
    c.handler = function(g, r){
        c.myHandler(g.getStore().getAt(r));
    }.bind(c);

    var col = new Ext.grid.ActionColumn(c);

    // "hideIf" es una propiedad definida por el usuario
    //   que oculta el boton del actionColumn si retorna true
    col.originalRenderer = col.renderer;
    col.renderer = function(v,m,r,ri,ci,s){
        if (typeof col.hideIf != 'undefined' && col.hideIf(v,m,r,ri,ci,s))
            return '';
        else
            return col.originalRenderer(v,m);
    }.bind(col);
    return col;
}

X.grid.hideif = function(gridId, colIndex, func){
    var cm = X.get(gridId).getColumnModel();
    var co = cm.getColumnById( cm.getColumnId(colIndex) );
        co.hideIf = func;
}

//==========================================//
//                  STORE                   //
//==========================================//

Ext.ns('X');

//Agregado
X.aStore = function(c){return new Ext.data.ArrayStore  (c);}
X.sStore = function(c){return new Ext.data.SimpleStore  (c);}

X.store = function(c){
    c.totalProperty = 'total';
    c.root       = 'rows';
    c.remoteSort = true;
    c.listeners  = {
        exception  : function(proxy, type, action, o, response, args){
            try{
                if (type=='response')
                    X.msg.failure('respuesta inválida del servidor');
                if (type=='remote')
                    X.msg.failure(response.raw.msg);
            }
            catch(e){
                X.msg.failure(e.message);
            }
        }
    }
    return new Ext.data.JsonStore(c);
}

//==========================================//
//                  RECORD                   //
//==========================================//
X.record = function(c){return new Ext.data.Record  (c);}


//==========================================//
//                 WINDOW                   //
//==========================================//

Ext.ns('X.win');

X.win.panel = function(c){
    c.renderTo = 'layout_content';
    if (typeof c.modal == 'undefined')
        c.modal    = true;
    c.border   = false;
    if (typeof c.closable == 'undefined')
        c.closable = false;
    return new Ext.Window(c);
};